<?php

namespace Nece\Sdk\Coze\Api;

use Nece\Sdk\Coze\ApiAbstract;

/**
 * 智能音视频
 *
 * @author gjw
 * @created 2025-04-23 14:10:00
 */
class Audio extends ApiAbstract
{
    /**
     * 查看音色列表
     *
     * @author gjw
     * @created 2025-04-23 15:45:32
     *
     * @param string $model_type 音色模型的类型，如果不填，默认都返回。可选值包括：big：大模型 small：小模型
     * @param boolean $filter_system_voice 查看音色列表时是否过滤掉系统音色。true：过滤系统音色 false：（默认）不过滤系统音色
     * @param string $voice_state 音色状态。可选值包括：cloned：已复刻，uncloned：未复刻，all：（默认）所有音色
     * @param integer $page_num 查询结果分页展示时，此参数用于设置查看的页码。最小值为 1，默认为 1。
     * @param integer $page_size 查询结果分页展示时，此参数用于设置每页返回的数据量。取值范围为 1~100，默认为 100。
     * @return array
     */
    public function voices(string $model_type = '', bool $filter_system_voice = false, $voice_state = 'cloned', int $page_num = 1, int $page_size = 10)
    {
        $api = '/v1/audio/voices';
        $query = array(
            'filter_system_voice' => $filter_system_voice,
            'voice_state' => $voice_state,
            'page_num' => $page_num,
            'page_size' => $page_size
        );

        if ($model_type) {
            $query['model_type'] = $model_type;
        }

        return $this->get($api, $query);
    }

    /**
     * 语音合成
     * 文档：https://www.coze.cn/open/docs/developer_guides/text_to_speech
     *
     * @author gjw
     * @created 2025-04-23 15:47:16
     *
     * @param string $input 合成语音的文本，经由 UTF-8 编码。长度限制为 1024 字节。
     * @param string $voice_id 音频文件使用的音色 ID。调用查看音色列表 API，可查看所有可用音色。
     * @param string $emotion 设置多情感音色的情感类型，仅当 voice_id 为多情感音色时才支持设置情感类型。不同音色支持的情感范围不同，可以通过系统音色列表查看各音色支持的情感。默认为空。
     * @param float $emotion_scale 情感值用于量化情感的强度。数值越高，情感表达越强烈，例如： “开心” 的情感值 5 比 1 更显兴奋。取值范围：1.0~5.0，默认值：4.0。
     * @param string $response_format 音频文件的编码格式，支持设置为：wav：返回二进制 wav 音频。pcm：返回二进制 pcm 音频。ogg_opus：返回多段含 opus 压缩分片音频。mp3：（默认）返回二进制 mp3 音频。
     * @param integer $speed 语速，取值范围为 0.2~3，通常保留一位小数即可。其中 0.2 表示 0.2 倍速，3 表示 3 倍速。默认为 1，表示 1 倍速。
     * @param integer $sample_rate 音频采样率，单位为 Hz。8000：8k 16000：16k 22050：22.05k 24000：（默认）24k 32000：32k 44100：44.1k 48000：48k
     * @return array
     */
    public function speech(string $input, string $voice_id, string $emotion = '', float $emotion_scale = 0, string $response_format = 'mp3', float $speed = 1, int $sample_rate = 24000)
    {
        $api = '/v1/audio/speech';
        $params = array(
            'input' => $input,
            'voice_id' => $voice_id,
            'response_format' => $response_format,
            'speed' => $speed,
            'sample_rate' => $sample_rate,
        );

        if ($emotion) {
            $params['emotion'] = $emotion;
        }
        if ($emotion_scale) {
            $params['emotion_scale'] = $emotion_scale;
        }

        return $this->post($api, $params);
    }

    /**
     * 语音识别
     *
     * @author gjw
     * @created 2025-04-23 15:48:39
     *
     * @param string $body 文件二进制数据，音频文件的详细限制可参考接口说明部分。
     * @return array
     */
    public function transcriptions(string $body)
    {
        $api = '/v1/audio/transcriptions';
        $params = array(
            'body' => $body,
        );

        return $this->post($api, $params);
    }

    /**
     * 复刻音色
     *
     * @author gjw
     * @created 2025-04-23 15:50:45
     *
     * @param string $voice_name 此音色的名称，长度限制为 128 字节。
     * @param string $text 音频文件对应的文案。需要和音频文件中人声朗读的内容大致一致，扣子平台服务会对比音频与该文本的差异，若差异过大会报错 1109 WERError。最大长度为 1024 字节。
     * @param string $language 音频文件中的语种，支持以下语种：zh：中文 en：英文 ja：日语 es：西班牙语 id：印度尼西亚语 pt：葡萄牙语
     * @param string $voice_id 需要训练的音色 ID，扣子平台支持重新复刻音色，也就是训练音色，训练后的音色会覆盖原有的音色。仅在训练音色时需要指定此参数。如果复刻一个新的音色，则无需指定此参数，扣子平台会为新音色分配一个音色 ID。
     * @param string $preview_text 预览音频的文案。如果成功复刻音色，扣子平台会根据此文案生成一段新音色的预览音频。未指定文案时，使用默认文案“你好，我是你的专属AI克隆声音，希望未来可以一起好好相处哦"。
     * @param string $space_id 克隆音色保存的扣子空间 ID，默认保存在当前账号的个人空间中。
     * @return array
     */
    public function clone(string $voice_name, string $text = '', string $language = '', string $voice_id = '', string $preview_text = '', string $space_id = '')
    {
        $api = '/v1/audio/voices/clone';

        $params = array(
            'voice_name' => $voice_name,
        );

        if (!empty($text)) {
            $params['text'] = $text;
        }
        if (!empty($language)) {
            $params['language'] = $language;
        }
        if (!empty($voice_id)) {
            $params['voice_id'] = $voice_id;
        }
        if (!empty($preview_text)) {
            $params['preview_text'] = $preview_text;
        }
        if (!empty($space_id)) {
            $params['space_id'] = $space_id;
        }

        return $this->post($api, $params);
    }

    /**
     * 创建房间
     *
     * @author gjw
     * @created 2025-08-05 10:48:18
     *
     * @param string $bot_id 智能体 ID。
     * @param string $conversation_id 会话 ID。后续调用发起对话 API 产生的消息记录都会保存在此对话中。调用创建会话 API 可以创建一个会话。若未指定会话 ID，扣子平台会默认创建一个新的会话。
     * @param string $voice_id 智能体使用的音色 ID，默认为柔美女友音色。
     * @param array $config 房间内的音视频参数配置。 https://www.coze.cn/open/docs/developer_guides/create_room#roomconfig
     * @param string $uid 标识当前与智能体的用户，由使用方自行定义、生成与维护。uid 用于标识对话中的不同用户，不同的 uid，其对话的数据库等对话记忆数据互相隔离。如果不需要用户数据隔离，可以不传此参数。
     * @param string $workflow_id 对话流 ID。在音视频对话中，可以设置对话流参数，自行控制对话数据的处理流程。此对话流无需和智能体绑定。使用方式如下：提前创建一个对话流，并在创建房间时指定对话流 ID 和智能体 ID，创建房间后可以再调用信令事件去传入 parameters 设置对话流的参数。然后就可以在对话流中使用 parameters 参数控制自己的业务流程。
     * @return array
     */
    public function createRoom(string $bot_id, string $conversation_id = '', string $voice_id = '', array $config = [], string $uid = '', string $workflow_id = '')
    {
        $api = '/v1/audio/rooms';

        $params = array(
            'bot_id' => $bot_id
        );

        if (!empty($conversation_id)) {
            $params['conversation_id'] = $conversation_id;
        }

        if (!empty($voice_id)) {
            $params['voice_id'] = $voice_id;
        }

        if (!empty($config)) {
            $params['config'] = $config;
        }
        if (!empty($uid)) {
            $params['uid'] = $uid;
        }

        if (!empty($workflow_id)) {
            $params['workflow_id'] = $workflow_id;
        }

        return $this->post($api, $params);
    }

    /**
     * 创建声纹组
     *
     * @author gjw
     * @created 2025-08-05 09:33:57
     *
     * @param string $name 声纹组名称，最长 20 个字符。
     * @param string $desc 声纹组描述，最长 500 个字符。
     * @return array
     */
    public function createVoiceprintGroup(string $name, string $desc)
    {
        $api = '/v1/audio/voiceprint_groups';
        $params = array(
            'name' => $name,
        );
        if ($desc) {
            $params['desc'] = $desc;
        }
        return $this->post($api, $params);
    }

    /**
     * 查询声纹组列表
     * 文档:https://www.coze.cn/open/docs/developer_guides/list_voiceprint_group
     *
     * @author gjw
     * @created 2025-08-05 09:37:11
     *
     * @param integer $page_num 查询结果分页展示时，此参数用于设置查看的页码。最小值为 1，默认为 1。
     * @param integer $page_size 查询结果分页展示时，此参数用于设置每页返回的数据量。取值范围为 1~200，默认为 10。
     * @param string $name 用于根据声纹组名称前缀进行模糊匹配筛选，支持输入部分名称前缀进行查询。
     * @param string $user_id 声纹创建者的扣子用户 ID。
     * @param string $group_id 声纹组 ID，用于指定查询特定的声纹组。
     * @return array
     */
    public function listVoiceprintGroup(int $page_num = 1, int $page_size = 10, string $name = '', string $user_id = '', string $group_id = '')
    {
        $api = '/v1/audio/voiceprint_groups';
        $query = array(
            'page_num' => $page_num,
            'page_size' => $page_size,
        );

        if ($name) {
            $query['name'] = $name;
        }
        if ($user_id) {
            $query['user_id'] = $user_id;
        }
        if ($group_id) {
            $query['group_id'] = $group_id;
        }
        return $this->get($api, $query);
    }

    /**
     * 更新声纹组信息
     *
     * @author gjw
     * @created 2025-08-05 09:44:43
     *
     * @param string $group_id 待更新的声纹组的 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @param string $name 更新后的声纹组名称，最长 20 个字符。
     * @param string $desc 更新后的声纹组描述，最长 500 个字符。
     * @return array
     */
    public function updateVoiceprintGroup(string $group_id, string $name, string $desc = '')
    {
        $api = '/v1/audio/voiceprint_groups/:group_id';
        $api = str_replace(':group_id', $group_id, $api);
        $params = array(
            'name' => $name,
        );

        if ($desc) {
            $params['desc'] = $desc;
        }

        return $this->post($api, $params, [], 'PUT');
    }

    /**
     * 删除声纹组
     *
     * @author gjw
     * @created 2025-08-05 09:48:03
     *
     * @param string $group_id 待删除的声纹组 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @return array
     */
    public function deleteVoiceprintGroup($group_id)
    {
        $api = '/v1/audio/voiceprint_groups/:group_id';
        $api = str_replace(':group_id', $group_id, $api);
        return $this->post($api, [], [], 'DELETE');
    }

    /**
     * 创建声纹
     *
     * @author gjw
     * @created 2025-08-05 09:50:52
     *
     * @param string $group_id 声纹所属的声纹组 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @param string $file 本地文件绝对路径，例：d:/a.wav。
     * @param string $name 声纹的名称。
     * @param string $desc 声纹的描述。
     * @param integer $sample_rate 采样率，单位：Hz。当文件类型为 pcm 时需传入该参数。默认为 16kHz 采样率。例：16000
     * @param integer $channel 声道数，当文件类型为 pcm 时需传入该参数。默认为单声道。
     * @return array
     */
    public function createVoiceprintFeature($group_id, $file, $name, $desc = '', $sample_rate = 0, $channel = 0)
    {
        $api = '/v1/audio/voiceprint_groups/:group_id/features';
        $api = str_replace(':group_id', $group_id, $api);
        $params = array(
            'name' => $name,
        );
        if ($desc) {
            $params['desc'] = $desc;
        }
        if ($sample_rate) {
            $params['sample_rate'] = $sample_rate;
        }
        if ($channel) {
            $params['channel'] = $channel;
        }

        $this->addFile('file', $file);

        return $this->post($api, $params);
    }

    /**
     * 更新声纹
     *
     * @author gjw
     * @created 2025-08-05 10:15:52
     *
     * @param string $group_id 声纹所属的声纹组 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @param string $feature_id 待更新的声纹 ID。
     * @param string $file 本地文件绝对路径，例：d:/a.wav。
     * @param string $name 声纹的名称。
     * @param string $desc 声纹的描述。
     * @param integer $sample_rate 采样率，单位：Hz。当文件类型为 pcm 时需传入该参数。默认为 16kHz 采样率。例：16000 
     * @param integer $channel 声道数，当文件类型为 pcm 时需传入该参数。默认为单声道。
     * @return array
     */
    public function updateVoiceprintFeature($group_id, $feature_id, $file, $name, $desc = '', $sample_rate = 0, $channel = 0)
    {
        $api = '/v1/audio/voiceprint_groups/:group_id/features/:feature_id';
        $api = str_replace(array(':group_id', ':feature_id'), array($group_id, $feature_id), $api);

        $params = array(
            'name' => $name,
        );
        if ($desc) {
            $params['desc'] = $desc;
        }
        if ($sample_rate) {
            $params['sample_rate'] = $sample_rate;
        }
        if ($channel) {
            $params['channel'] = $channel;
        }

        $this->addFile('file', $file);

        return $this->post($api, $params, [], 'PUT');
    }

    /**
     * 查询声纹列表
     *
     * @author gjw
     * @created 2025-08-05 10:24:14
     *
     * @param string $group_id 声纹组 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @param integer $page_num 查询结果分页展示时，此参数用于设置查看的页码。最小值为 1，默认为 1。
     * @param integer $page_size 查询结果分页展示时，此参数用于设置每页返回的数据量。取值范围为 1~200，默认为 10。
     * @return array
     */
    public function listVoiceprintFeature($group_id, $page_num = 1, $page_size = 10)
    {
        $api = '/v1/audio/voiceprint_groups/:group_id/features';
        $api = str_replace(':group_id', $group_id, $api);
        $query = array(
            'page_num' => $page_num,
            'page_size' => $page_size,
        );
        return $this->get($api, $query);
    }

    /**
     * 删除声纹
     *
     * @author gjw
     * @created 2025-08-05 10:26:03
     *
     * @param string $group_id 声纹所属的声纹组 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @param string $feature_id 待删除的声纹 ID。你可以通过查看声纹列表 API 查看声纹 ID。
     * @return array
     */
    public function deleteVoiceprintFeature($group_id, $feature_id)
    {
        $api = '/v1/audio/voiceprint_groups/:group_id/features/:feature_id';
        $api = str_replace(array(':group_id', ':feature_id'), array($group_id, $feature_id), $api);
        return $this->post($api, [], [], 'DELETE');
    }

    /**
     * 声纹特征比对
     *
     * @author gjw
     * @created 2025-08-05 10:29:50
     *
     * @param string $group_id 声纹所属的声纹组 ID。你可以通过查看声纹组列表 API 查看声纹组 ID。
     * @param string $file 本地文件绝对路径，例：d:/a.wav。
     * @param integer $top_k 返回特征匹配度最高的前 k 项结果。若未指定，则默认返回全部匹配结果。
     * @param integer $sample_rate 采样率，单位：Hz。当文件类型为 pcm 时需传入该参数。默认的采样率为 16kHz。例：16000 
     * @param integer $channel 声道数，当文件类型为 pcm 时需传入该参数。默认为单声道。
     * @return array
     */
    public function identifyInVoiceprintGroup($group_id, $file, $top_k = 0, $sample_rate = 0, $channel = 0)
    {
        $api = '/v1/audio/voiceprint_groups/:group_id/speaker_identify';
        $api = str_replace(':group_id', $group_id, $api);

        $params = array();
        if ($top_k) {
            $params['top_k'] = $top_k;
        }
        if ($sample_rate) {
            $params['sample_rate'] = $sample_rate;
        }
        if ($channel) {
            $params['channel'] = $channel;
        }
        $this->addFile('file', $file);
        return $this->post($api, $params);
    }
}
